package cn.signalpha.modules.pay.service;

import cn.signalpha.common.utils.Arith;
import cn.signalpha.common.utils.Assert;
import cn.signalpha.common.utils.SnowflakeUtil;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.tool.jackson.JsonUtil;
import cn.signalpha.core.tool.utils.Func;
import cn.signalpha.core.tool.utils.StringPool;
import cn.signalpha.core.tool.utils.StringUtil;
import cn.signalpha.modules.com.entity.User;
import cn.signalpha.modules.com.service.UserService;
import cn.signalpha.modules.pay.dto.PayDTO;
import cn.signalpha.modules.shop.dto.OrderLogisticsDTO;
import cn.signalpha.modules.shop.entity.Order;
import cn.signalpha.modules.shop.entity.OrderSettle;
import cn.signalpha.modules.shop.entity.Seller;
import cn.signalpha.modules.shop.entity.enums.LogisticsTypeEnum;
import cn.signalpha.modules.shop.event.OrderPaySuccessEvent;
import cn.signalpha.modules.shop.service.CityDeliveryService;
import cn.signalpha.modules.shop.service.OrderService;
import cn.signalpha.modules.shop.service.OrderSettleService;
import cn.signalpha.modules.shop.service.SellerService;
import cn.signalpha.modules.shop.vo.SellerDeliveryConfigVO;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 类说明
 *
 * @author signalpha
 */
@Slf4j
@Service
@AllArgsConstructor
public class PayService {

	private final UserService userService;
	private final OrderService orderService;
	private final SellerService sellerService;
	private final SnowflakeUtil snowflakeUtil;
	private final OrderSettleService orderSettleService;
	private final CityDeliveryService cityDeliveryService;
	private final ApplicationEventPublisher eventPublisher;

	/**
	 * 订单支付参数组装
	 */
	@Transactional(rollbackFor = Exception.class)
	public PayDTO orderPay(Long userId, String orderNo) {
		StringBuilder goodsName = new StringBuilder();
		String payNo = snowflakeUtil.snowflakeId();

		//校验用户余额和积分
		double money = 0, integral = 0;
		List<String> orderNoList = Func.toStrList(orderNo);
		for(String item : orderNoList){
			Order order = orderService.getByOrderNo(item);
			Assert.isNull(order, StringUtil.format("订单号[{}]不存在", item));
			Assert.isTrue(order.getOrderStatus() == 0, "请不要重复支付");

			OrderSettle orderSettle = new OrderSettle();
			orderSettle.setPayNo(payNo);
			orderSettle.setPayType(StringPool.EMPTY);
			orderSettleService.update(orderSettle, Wrappers.<OrderSettle>lambdaUpdate().eq(OrderSettle::getOrderNo, item));
//			orderSettleService.update(orderSettle, Wrappers.<OrderSettle>lambdaUpdate().eq(OrderSettle::getUserId, userId).eq(OrderSettle::getOrderNo, item));

			money = Arith.add(money, order.getDeductMoney());
			integral = Arith.add(integral, order.getDeductIntegral());
			goodsName.append(order.getGoodsName()).append(StringPool.COMMA);
		}

		User user = userService.getById(userId);
		if(money > 0 && user.getMoney() < money){
			throw new ServiceException("余额不足");
		}
		if(integral > 0 && user.getIntegral() < integral){
			throw new ServiceException("积分不足");
		}

		// 除了orderNo不一样，其他都一样
		List<OrderSettle> orderSettleList = orderSettleService.getByPayNo(payNo);
		double payAmount = 0d;
		for (OrderSettle orderSettle : orderSettleList) {
			payAmount = Arith.add(payAmount, orderSettle.getPayAmount());
		}

		String body = goodsName.toString();
		if(goodsName.length() > 32){
			body = goodsName.substring(0, 32);
		}
		PayDTO payDTO = new PayDTO();
		payDTO.setUserId(userId);
		payDTO.setPayMoney(String.valueOf(payAmount));
		payDTO.setPayNo(payNo);
		payDTO.setBody(body);
		payDTO.setParams(orderNo);
		payDTO.setNotifyParams(payNo);
		payDTO.setIsSharing(1);
		return payDTO;
	}

	/**
	 * 订单支付成功处理
	 */
	public void orderPaySuccess(String payNo, String bizPayNo, String payType) {
		if(orderSettleService.updateByPaySuccess(payNo, bizPayNo, payType) == 0){
			//支付单号被改变，进入补救措施
			log.warn(bizPayNo, "支付单号为空：" + payNo);
		}

		List<String> orderNoList = orderSettleService.getByPayNo(payNo).stream().map(OrderSettle::getOrderNo).collect(Collectors.toList());
		orderService.updateByPaySuccess(orderNoList, payType);
		List<Order> orderList = orderService.list(Wrappers.<Order>lambdaQuery().in(Order::getOrderNo, orderNoList));
		eventPublisher.publishEvent(new OrderPaySuccessEvent(orderList));

		orderList.forEach(order -> {
			if(order.getLogisticsType().equals(LogisticsTypeEnum.DELIVERY.getType())){
				Seller seller = sellerService.getById(order.getSellerId());
				SellerDeliveryConfigVO sellerDeliveryConfig = JsonUtil.parse(seller.getDeliveryConfig(), SellerDeliveryConfigVO.class);
				if(sellerDeliveryConfig.getIsOpenAuto() == 1){
					orderService.logisticsSave(OrderLogisticsDTO.builder().orderId(order.getId()).logisticsType(1).build());
				}
			}
		});
	}

}
